package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.article.IArticleClient;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.exception.CustomException;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Author 刘旭
 * @Date 2022/8/31 20:26
 * @Description:
 */
@Service
@Slf4j
@Transactional
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private WmChannelMapper wmChannelMapper;
    @Autowired
    private IArticleClient iArticleClient;
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private FileStorageService fileStorageService;
    @Autowired
    GreenImageScan greenImageScan;
    @Autowired
    WmSensitiveMapper wmSensitiveMapper;
    @Autowired
    Tess4jClient tess4jClient;

    /**
     * 自动审核接口
     *
     * @param id 自媒体文章Id
     */
    @Async
    @Override
    public void autoScanWmNews(Integer id) {
        //校验参数
        if (id == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //抽取所有的图片和文本到一个map中，方便审核
        Map<String, Object> maps = handleTextAndImages(wmNews);
        //抽取图片中的文本数据
        //构建一个变量存储图片中的文字
        StringBuffer stringBuffer = new StringBuffer();
        //获取所有图片
        List<String> imagList = (List<String>) maps.get("images");
        //图片去重
        imagList = imagList.stream().distinct().collect(Collectors.toList());
        //循环读取图片中的文字即可
        for (String img : imagList) {
            //下载图片
            byte[] bytes = fileStorageService.downLoadFile(img);
            //把字节数组转换成一个StringBuffer对象
            ByteArrayInputStream is = new ByteArrayInputStream(bytes);
            try {
                BufferedImage imgFile = ImageIO.read(is);
                String s = tess4jClient.doOCR(imgFile);
                stringBuffer.append(s + "-");
            } catch (Exception e) {
                e.printStackTrace();

            }
            maps.put("content", maps.get("content") + stringBuffer.toString());


        }
        // ****************************************************8
        //先进行一个自敏感词的审核
        //查询文本去匹配敏感词数据
        List<WmSensitive> wmSensitiveList = wmSensitiveMapper.selectList(null);
        List<String> wmSensitives = wmSensitiveList.stream().map(c -> c.getSensitives()).collect(Collectors.toList());

        //根据DfA工具类生成一个算法表
        SensitiveWordUtil.initMap(wmSensitives);
        //使用文本去匹配敏感词数据
        Map<String, Integer> content = SensitiveWordUtil.matchWords((String) maps.get("content"));
        if (content.size() > 0) {
            //修改文章状态，拒绝原因
            wmNews.setStatus((short) 2);
            wmNews.setReason("敏感词违规");
            wmNewsMapper.updateById(wmNews);
            return;
        }
        //*****************************************************
        //审核文本
        Boolean textFlag = handleTextScan(wmNews, (String) maps.get("content"));
        if (!textFlag) {
            return;
        }
        //审核图片 气死个人，讲挂就一声 哼 ！
        Boolean imgFlag = handleImagesScan(wmNews, (List<String>) maps.get("images"));
        //审核通过，保存app端相关文章数据
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, articleDto);
        //封装作者信息
        articleDto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        articleDto.setAuthorName(wmUser.getName());
        //分类名字
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if (wmChannel != null) {
            articleDto.setAuthorName(wmChannel.getName());

        }
        //修改文章布局
        articleDto.setLayout(wmNews.getType());
        //设置文章Id
        if (wmNews.getArticleId() != null) {
            articleDto.setId(wmNews.getArticleId());
        }
        ResponseResult responseResult = iArticleClient.saveArticle(articleDto);
        //修改自媒体文章审核状体，结束
        if (responseResult.getCode() != 200) {
            throw new RuntimeException("请求失败。。。。");
        }
        wmNews.setArticleId((Long) responseResult.getData());
        wmNews.setStatus((short) 9);
        wmNews.setReason("审核成功");
        wmNewsMapper.updateById(wmNews);


    }

    private Boolean handleImagesScan(WmNews wmNews, List<String> images) {
        //处理一下图片
        //重复的图片去重
        images = images.stream().distinct().collect(Collectors.toList());
        //把图片从minio上，下载下来变成字节数据
        ArrayList<byte[]> imageList = new ArrayList<>();
        images.stream().forEach(image -> {
            imageList.add(fileStorageService.downLoadFile(image));
        });
        //开始审核
        try {
            Map map = greenImageScan.imageScan(imageList);
            if (map.get("suggestion").equals("block")) {
                wmNews.setReason("图片违规");
                wmNews.setStatus((short) 2);
                wmNewsMapper.updateById(wmNews);
                return false;
            }
            if (map.get("suggestion").equals("review")) {
                //阿里云不能确定，转人工审核
                wmNews.setStatus((short) 3);
                wmNewsMapper.updateById(wmNews);
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private Boolean handleTextScan(WmNews wmNews, String content) {
        try {
            Map map = greenTextScan.greeTextScan(content);
            if (map.get("suggestion").equals("block")) {
                wmNews.setReason("文本违规");
                wmNews.setStatus((short) 2);
                wmNewsMapper.updateById(wmNews);
                return false;
            }
            if (map.get("suggestion").equals("review")) {
                //阿里云不能确定，转人工审核
                wmNews.setStatus((short) 3);
                wmNewsMapper.updateById(wmNews);
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        //构建两个东西来存储图片和文字
        ArrayList<String> imgs = new ArrayList<>();
        StringBuffer sb = new StringBuffer();
        //从文章内容中抽取文字和图片
        List<Map> maps = JSON.parseArray(wmNews.getContent(), Map.class);

        //遍历找值
        for (Map map : maps) {
            if (map.get("type").equals("text")) {
                sb.append(map.get("value"));
            }
            if (map.get("type").equals("image")) {
                imgs.add((String) map.get("value"));
            }
        }
        //提取文章封面的图片
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            String[] split = wmNews.getImages().split(",");
            imgs.addAll(Arrays.asList(split));
        }
        //提取标题中的文本和标签中的文本
        sb.append(wmNews.getTitle());
        sb.append(wmNews.getLabels());
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("content", sb.toString());
        resultMap.put("images", imgs);
        return resultMap;
    }
}